package org.performancetracker.servlet25;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

import org.performancetracker.api.Tracker;
import org.performancetracker.api.Aggregator;
import org.performancetracker.AggregatorFactory;
import org.performancetracker.TrackerFactory;

/**
 * This filter catches trackers on their way out, preferably the tracker was added to the request when the viewrendering started.
 *
 * @author: jaronschut
 */

public class ViewRenderingMonitoringFilter implements Filter {
    private static final String LOG_INIT_1 = ": Initializing ViewRenderingMonitoringFilter, bindParam set to '";
    private static final String LOG_INIT_2 = "', aggregatorName set to '";
    private static final String LOG_INIT_3 = "'";

    private static final String CONFIG_BIND_PARAM = "bindParam";
    private static final String DEFAULT_BIND_PARAM = ViewRenderingMonitoringFilter.class.getName();

    private static final String CONFIG_AGGRAGATOR_NAME = "aggregatorName";
    private static final String DEFAULT_AGGREGATOR_NAME = "Tracker.Web.View";

    private static String BIND_PARAM = DEFAULT_BIND_PARAM;
    private static String AGGREGATOR_NAME = DEFAULT_AGGREGATOR_NAME;
    private static Aggregator TRACKER_AGGREGATOR;

    private FilterConfig filterConfig;

    /**
     * Method of Filter interface, perform the performance tracking.
     *
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        try {

            filterChain.doFilter(servletRequest, servletResponse);
            
        } finally {
        
            // Close the monitor
            if (servletRequest instanceof HttpServletRequest) {
                Object tracker = ((HttpServletRequest) servletRequest).getAttribute(BIND_PARAM);
                if (tracker instanceof Tracker) {
                    ((Tracker)tracker).stop().aggregate("");
                }
            }

        }
    }

    /**
     * Start of filter live.
     *
     * @param filterConfig
     * @throws ServletException
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        Tracker tracker = TrackerFactory.startTracker();

        this.filterConfig = filterConfig;

        if (filterConfig.getInitParameter(CONFIG_BIND_PARAM) != null) {
            BIND_PARAM = filterConfig.getInitParameter(CONFIG_BIND_PARAM);
        }

        if (filterConfig.getInitParameter(CONFIG_AGGRAGATOR_NAME) != null) {
            AGGREGATOR_NAME = filterConfig.getInitParameter(CONFIG_AGGRAGATOR_NAME);
        }

        TRACKER_AGGREGATOR = AggregatorFactory.createTrackerAggregator(AGGREGATOR_NAME);

        tracker.stop().aggregate(ViewRenderingMonitoringFilter.class.getSimpleName()
                + LOG_INIT_1
                + BIND_PARAM
                + LOG_INIT_2
                + AGGREGATOR_NAME
                + LOG_INIT_3);
    }

    /**
     * End of Filter life.
     *
     */
    public void destroy() {
        TRACKER_AGGREGATOR = null;
        BIND_PARAM = null;
        filterConfig = null;
    }

    /**
     * Get the variable name under which the tracker is bound to the SerlvetRequest.
     *
     * @return
     */
    public static String getBindParamName() {
        return BIND_PARAM;
    }

    /**
     * Get the tracker to bind in case it needs to be bound manually.
     *
     * @return
     */
    public static Tracker getTracker() {
        return TrackerFactory.startTracker(TRACKER_AGGREGATOR);
    }

    /**
     * Regular method to set the tracker.
     *
     * @param httpServletRequest
     */
    public static void bindTracker(HttpServletRequest httpServletRequest) {
        httpServletRequest.setAttribute(getBindParamName(), getTracker());
    }
}